package com.chenfan.mcn.mq.producer;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.chenfan.mcn.clients.baseinfo.BaseCustomer;
import com.chenfan.mcn.clients.baseinfo.BaseInfoClient;
import com.chenfan.mcn.clients.baseinfo.DescByCodeDTO;
import com.chenfan.mcn.constant.NumberCst;
import com.chenfan.mcn.constant.SeparatorCst;
import com.chenfan.mcn.dao.ContractExcutionOrderMapper;
import com.chenfan.mcn.dao.IncomeContactAgreementMapper;
import com.chenfan.mcn.dao.IncomeContractMapper;
import com.chenfan.mcn.enums.*;
import com.chenfan.mcn.exception.McnErrorCode;
import com.chenfan.mcn.model.ContractExcutionOrder;
import com.chenfan.mcn.model.IncomeContract;
import com.chenfan.mcn.model.IncomeContractAgreement;
import com.chenfan.mcn.mq.AbstractMessageProducer;
import com.chenfan.mcn.mq.MessageProducer;
import com.chenfan.mcn.mq.message.CfChargeCommonMessage;
import com.chenfan.mcn.utils.BusinessAssert;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author:   tangwei
 * Date:     2021/3/4 10:06
 * Description: 收入合同补充协议审批通过生成费用推送财务系统
 */

@Slf4j
@Service
public class IncomeContractAgreementMessageProducer extends AbstractMessageProducer implements MessageProducer<Long> {

    @Autowired
    private IncomeContactAgreementMapper incomeContactAgreementMapper;

    @Autowired
    private IncomeContractMapper incomeContractMapper;

    @Autowired
    private ContractExcutionOrderMapper contractExcutionOrderMapper;

    @Autowired
    private BaseInfoClient baseInfoClient;

    @Async
    @Override
    public void asyncSendRecordToMq(Long agreementId) {
        log.info("进入收入合同补充协议生成费用推送MQ方法==》agreementId={}",agreementId);
        IncomeContractAgreement incomeContractAgreement = incomeContactAgreementMapper.selectById(agreementId);
        BusinessAssert.notNull(incomeContractAgreement, McnErrorCode.AGREEMENT_NOT_EXISTS);
        IncomeContract incomeContract = incomeContractMapper.selectById(incomeContractAgreement.getIncomeContractId());
        BusinessAssert.notNull(incomeContract, McnErrorCode.INCOME_NOT_EXISTS);
        Map<Long, BaseCustomer> customerMap = baseInfoClient.getMcnCustomerByIds(Collections.singletonList(incomeContract.getCustomerId())).getObj();
        List<ContractExcutionOrder> excutionOrderList = contractExcutionOrderMapper.selectList(Wrappers.lambdaQuery(ContractExcutionOrder.class)
                .eq(ContractExcutionOrder::getIncomeContractId, incomeContract.getId())
                .eq(ContractExcutionOrder::getContractAgreementId, incomeContractAgreement.getId())
                .ne(ContractExcutionOrder::getApprovalStatus, ExcutionApprovalStatusEnum.INVALID.code())
                .eq(ContractExcutionOrder::getIsDelete, NumberCst.ZERO));
        List<CfChargeCommonMessage> chargeList = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(excutionOrderList)) {
            Map<String, String> orderPlatformMap = this.getOrderPlatformMap(incomeContract, excutionOrderList);
            excutionOrderList.forEach(excutionOrder -> {
                //如果是形式合同且账号未入驻，等执行单审批通过才发送费用
                if(IncomeContractTypeEnum.isFormalContract(incomeContract.getContractType()) && NumberCst.ZERO.equals(excutionOrder.getInSystemAdmin())) {
                    return;
                }
                //如果是框架合同-是平台下单-未入驻红人
                if (IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType()) &&
                        ObjectUtils.defaultIfNull(excutionOrder.getPlatformReport(), Boolean.FALSE).booleanValue()
                        && NumberCst.ZERO.equals(excutionOrder.getInSystemAdmin())) {
                    return;
                }
                chargeList.add(this.buildChargeMessage(incomeContract, incomeContractAgreement, excutionOrder, customerMap, orderPlatformMap));
            });
        }
        if(CollectionUtils.isNotEmpty(chargeList)) {
            //推送费用MQ消息
            chargeList.forEach(charge -> {
                this.doSendRecordToMq(incomeContractAgreement.getAgreementCode(), charge, this.financeTopic);
            });
        }
    }

    /**
     * 构建收入合同费用消息
     * @param incomeContract
     * @param excutionOrder
     * @param customerMap
     * @return
     */
    private CfChargeCommonMessage buildChargeMessage(IncomeContract incomeContract, IncomeContractAgreement incomeContractAgreement, ContractExcutionOrder excutionOrder, Map<Long, BaseCustomer> customerMap, Map<String, String> orderPlatformMap) {
        CfChargeCommonMessage chargeMessage = new CfChargeCommonMessage();
        if(IncomeContractTypeEnum.isFormalContract(incomeContract.getContractType())) {
            chargeMessage.setChargeType(FinanceChargeTypeEnum.YES_FORMAL_CONTRACT_CHARGE.getType());
            chargeMessage.setAccountId(null);
            chargeMessage.setBalance(orderPlatformMap.get(excutionOrder.getOrderPlatform()));
        } else if(IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType())) {
            if(ObjectUtils.defaultIfNull(excutionOrder.getPlatformReport(), Boolean.FALSE).booleanValue() && NumberCst.ONE.equals(excutionOrder.getInSystemAdmin())) {
                chargeMessage.setChargeType(FinanceChargeTypeEnum.ONLINE_YES_ADVERTISING_CHARGE.getType());
                chargeMessage.setBalance(orderPlatformMap.get(excutionOrder.getOrderPlatform()));
            } else {
                chargeMessage.setChargeType(FinanceChargeTypeEnum.OFFLINE_ADVERTISING_CHARGE.getType());
                chargeMessage.setBalance(customerMap.get(incomeContract.getCustomerId()).getCustomerNameC());
            }
            chargeMessage.setAccountId(null);
        } else {
            chargeMessage.setChargeType(FinanceChargeTypeEnum.INCOME_CONTRACT_CHARGE.getType());
            chargeMessage.setAccountId(incomeContract.getCustomerBillingId());
            chargeMessage.setBalance(customerMap.get(incomeContract.getCustomerId()).getCustomerNameC());
        }
        chargeMessage.setArapType(FinanceArapTypeEnum.RECEIVE.getType());
        chargeMessage.setChargeSourceCode(incomeContract.getContractCode());
        chargeMessage.setChargeSourceDetail(excutionOrder.getExcuteCode());
        chargeMessage.setChargeSourceDetail2(excutionOrder.getPlatformOrderCode());
        chargeMessage.setAmountPp(excutionOrder.getActualQuotedPrice());
        chargeMessage.setPricePp(excutionOrder.getActualQuotedPrice());
        chargeMessage.setFinanceEntity(incomeContract.getCompanyContractSubject());
        chargeMessage.setCreateBy(incomeContractAgreement.getCreateBy());
        chargeMessage.setCreateName(incomeContractAgreement.getCreateName());
        chargeMessage.setCreateDate(new Date());
        chargeMessage.setUpdateBy(incomeContractAgreement.getCreateBy());
        chargeMessage.setUpdateDate(chargeMessage.getCreateDate());
        chargeMessage.setUpdateName(incomeContractAgreement.getCreateName());
        chargeMessage.setTenantId(incomeContractAgreement.getTenantId());
        chargeMessage.setCompanyId(incomeContractAgreement.getCompanyId());
        chargeMessage.setSettTemplate(null);
        chargeMessage.setTaxRate(BigDecimal.ZERO);
        if (InvoiceFormEnum.NO_NEED_INVOICE.getType().equals(incomeContract.getInvoiceForm())) {
            chargeMessage.setAccountId(null);
        }
        chargeMessage.setBalanceType(NumberCst.TWO);
        return chargeMessage;
    }

    /**
     * 构建直播生成合同费用
     * @param incomeContract
     * @param customerMap
     * @param feeAmount
     * @return
     */
    @Deprecated
    private CfChargeCommonMessage buildLiveChargeMessage(IncomeContract incomeContract, IncomeContractAgreement incomeContractAgreement, Map<Long, BaseCustomer> customerMap, BigDecimal feeAmount) {
        CfChargeCommonMessage chargeMessage = new CfChargeCommonMessage();
        chargeMessage.setChargeType(FinanceChargeTypeEnum.LIVE_CONTRACT_CHARGE.getType());
        chargeMessage.setArapType(FinanceArapTypeEnum.RECEIVE.getType());
        chargeMessage.setChargeSourceCode(incomeContract.getContractCode());
        chargeMessage.setChargeSourceDetail(incomeContractAgreement.getAgreementCode());
        chargeMessage.setAmountPp(feeAmount);
        chargeMessage.setPricePp(feeAmount);
        chargeMessage.setBalance(customerMap.get(incomeContract.getCustomerId()).getCustomerNameC());
        chargeMessage.setFinanceEntity(incomeContract.getCompanyContractSubject());
        chargeMessage.setCreateBy(incomeContractAgreement.getCreateBy());
        chargeMessage.setCreateName(incomeContractAgreement.getCreateName());
        chargeMessage.setCreateDate(new Date());
        chargeMessage.setUpdateBy(incomeContractAgreement.getCreateBy());
        chargeMessage.setUpdateDate(chargeMessage.getCreateDate());
        chargeMessage.setUpdateName(incomeContractAgreement.getCreateName());
        chargeMessage.setTenantId(incomeContractAgreement.getTenantId());
        chargeMessage.setCompanyId(incomeContractAgreement.getCompanyId());
        chargeMessage.setSettTemplate(null);
        chargeMessage.setTaxRate(BigDecimal.ZERO);
        /**
         * version:V1.16.1: 新增【财务信息ID+结算主体类型】
         */
        if (InvoiceFormEnum.NO_NEED_INVOICE.getType().equals(incomeContract.getInvoiceForm())) {
            chargeMessage.setAccountId(null);
        } else {
            chargeMessage.setAccountId(incomeContract.getCustomerBillingId());
        }
        chargeMessage.setBalanceType(NumberCst.TWO);
        return chargeMessage;
    }

    /**
     * 获取订单平台翻译Mao
     * @param excutionOrderList
     * @return
     */
    private Map<String, String> getOrderPlatformMap(IncomeContract incomeContract, List<ContractExcutionOrder> excutionOrderList) {
        if(CollectionUtils.isNotEmpty(excutionOrderList)) {
            List<String> orderPlatform = excutionOrderList.stream().filter(e -> StringUtils.isNotBlank(e.getOrderPlatform()))
                    .map(ContractExcutionOrder::getOrderPlatform).distinct().collect(Collectors.toList());
            Map<String, String> dictsNameMap = baseInfoClient.getDescByCode(new DescByCodeDTO()
                    .setProfileCodes(Arrays.asList("formal_contract"))
                    .setDictsCodes(orderPlatform)).getObj();
            return orderPlatform.stream().collect(Collectors.toMap(k -> k, v -> dictsNameMap.get("formal_contract" + SeparatorCst.SEMICOLON + v)));
        }
        return new HashMap<>(0);
    }
}
